<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 老猫 <thinkcmf@126.com>
// +----------------------------------------------------------------------
namespace app\goods\service;


use app\goods\model\GoodsModel;
use app\goods\model\GoodsCategoryModel;
use think\Db;

class GoodsApiService
{
    /**
     * 功能:查询文章列表,支持分页;<br>
     * 注:此方法查询时关联三个表goods_category_relate(category_relate),goods_goods(goods),user;在指定排序(order),指定查询条件(where)最好指定一下表别名
     * @param array $param 查询参数<pre>
     * array(
     *  'category_ids'=>'',
     *  'where'=>'',
     *  'limit'=>'',
     *  'order'=>'',
     *  'page'=>'',
     *  'relation'=>''
     * )
     * 字段说明:
     * category_ids:文章所在分类,可指定一个或多个分类id,以英文逗号分隔,如1或1,2,3 默认值为全部
     * field:调用指定的字段@todo
     *   如只调用goodss表里的id和goods_title字段可以是goods.id,goods.goods_title; 默认全部,
     *   此方法查询时关联三个表goods_category_relate(category_relate),goods_goods(goods),user;
     *   所以最好指定一下表名,以防字段冲突
     * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
     * order:排序方式,如按goodss表里的published_time字段倒序排列：goods.published_time desc
     * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突,查询条件(只支持数组),格式和thinkPHP的where方法一样,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突;
     * </pre>
     * @return array 包括分页的文章列表<pre>
     * 格式:
     * array(
     *     "goods"=>array(),//文章列表,array
     *     "page"=>"",//生成的分页html,不分页则没有此项
     *     "total"=>100, //符合条件的文章总数,不分页则没有此项
     *     "total_pages"=>5 // 总页数,不分页则没有此项
     * )</pre>
     */
    public static function goods($param)
    {
        $goodsPostModel = new GoodsModel();

        $where = [
            'goods.published_time'    => [['> time', 0], ['<', time()]],
            'goods.post_status'       => 99,
            'goods.delete_time'       => 0,
            'category_relate.is_show' => 1,
        ];

        $paramWhere = empty($param['where']) ? '' : $param['where'];

        // $limit       = empty($param['limit']) ? 10 : $param['limit'];
        $limit       = empty($param['limit']) ? '' : $param['limit'];
        $order       = empty($param['order']) ? '' : $param['order'];
        $page        = isset($param['page']) ? $param['page'] : false;
        $relation    = empty($param['relation']) ? '' : $param['relation'];
        $categoryIds = empty($param['category_ids']) ? '' : $param['category_ids'];

        $join = [
            // ['__USER__ user', 'goods.user_id = user.id'],
        ];

        if (!empty($categoryIds)) {

            $field = !empty($param['field']) ? $param['field'] : 'goods.*,category_relate.category_id';
            array_push($join, ['__GOODS_CATEGORY_RELATE__ category_relate', 'goods.goods_id = category_relate.goods_id']);

            if (!is_array($categoryIds)) {
                $categoryIds = explode(',', $categoryIds);
            }

            if (count($categoryIds) == 1) {
                $where['category_relate.category_id'] = $categoryIds[0];
            } else {
                $where['category_relate.category_id'] = ['in', $categoryIds];
            }

        } else {
            $field = !empty($param['field']) ? $param['field'] : 'goods.*,category_relate.category_id';
            array_push($join, ['__GOODS_CATEGORY_RELATE__ category_relate', 'goods.goods_id = category_relate.goods_id']);
        }

        $where['category.is_show'] = 1;
        array_push($join, ['__GOODS_CATEGORY__ category', 'category_relate.category_id = category.id']);

        $goods = $goodsPostModel->alias('goods')->field($field)
            ->join($join)
            ->where($where)
            ->where($paramWhere)
            ->order($order);

        $return = [];

        if (empty($page)) {

            $goods = $goods->limit($limit)->select();

            if (!empty($relation) && !empty($goods['items'])) {
                $goods->load($relation);
            }

            $return['goods'] = $goods;
        } else {
            if (is_array($page)) {
                if (empty($page['list_rows'])) {
                    $page['list_rows'] = 10;
                }

                $goods = $goods->paginate($page);
            } else {
                $goods = $goods->paginate(intval($page));
            }

            if (!empty($relation) && !empty($goods['items'])) {
                $goods->load($relation);
            }

            $goods->appends(request()->param());

            $return['goods']       = $goods->items();
            $return['page']        = $goods->render();
            $return['total']       = $goods->total();
            $return['total_pages'] = $goods->lastPage();
        }

        // echo $goodsPostModel->getLastsql();die;
        return $return;

    }


    /**
     * 返回指定分类
     * @param int $id 分类id
     * @return array 返回符合条件的分类
     */
    public static function category($id)
    {
        $goodsCategoryModel = new GoodsCategoryModel();

        $where = [
            'is_show'      => 1,
            'delete_time' => 0,
            'id'          => $id
        ];

        return $goodsCategoryModel->where($where)->find();
    }

    /**
     * 返回指定分类下的子分类
     * @param int $categoryId 分类id
     * @return false|\PDOStatement|string|\think\Collection 返回指定分类下的子分类
     */
    public static function subCategories($categoryId, $tag='', $where=array())
    {
        $goodsCategoryModel = new GoodsCategoryModel();

        $sql = [
            'is_show'      => 1,
            'delete_time' => 0,
            'parent_id'   => $categoryId,
            'is_show'     => 1,

        ];
        
        $param = cmf_param_lable($tag);
        $field = empty($param['field']) ? 'id,name' : $param['field'];
        $limit = empty($param['limit']) ? '' : $param['limit'];

        $terms = $goodsCategoryModel
              -> field($field)
              -> where($sql)
              -> where($where)
              -> order('list_order asc,id desc')
              -> limit($limit)
              -> select();
        // pre($goodsCategoryModel->getLastsql());
        return $terms;
    }

    /**
     * 返回指定分类下的所有子分类
     * @param int $categoryId 分类id
     * @return array 返回指定分类下的所有子分类
     */
    public static function allSubCategories($categoryId)
    {
        $goodsCategoryModel = new GoodsCategoryModel();

        $categoryId = intval($categoryId);

        if ($categoryId !== 0) {
            $category = $goodsCategoryModel->field('path')->where('id', $categoryId)->find();

            if (empty($category)) {
                return [];
            }

            $categoryPath = $category['path'];
        } else {
            $categoryPath = 0;
        }

        $where = [
            'is_show'      => 1,
            'delete_time' => 0,
            'path'        => ['like', "$categoryPath-%"]
        ];

        return $goodsCategoryModel->where($where)->select();
    }

    /**
     * 返回符合条件的所有分类
     * @param array $param 查询参数<pre>
     * array(
     *  'where'=>'',
     *  'order'=>'',
     * )</pre>
     * @return false|\PDOStatement|string|\think\Collection
     */
    public static function categories($param)
    {
        $paramWhere = empty($param['where']) ? '' : $param['where'];

        $order = empty($param['order']) ? '' : $param['order'];

        $goodsCategoryModel = new GoodsCategoryModel();

        $where = [
            'is_show'      => 1,
            'delete_time' => 0,
        ];

        return $goodsCategoryModel
            ->where($where)
            ->where($paramWhere)
            ->order($order)
            ->select();
    }

    /**
     * 获取面包屑数据
     * @param int $categoryId 当前文章所在分类,或者当前分类的id
     * @param boolean $withCurrent 是否获取当前分类
     * @return array 面包屑数据
     */
    public static function breadcrumb($categoryId, $withCurrent = false,$tag='',$where='')
    {
        $data                = [];
        $goodsCategoryModel = new GoodsCategoryModel();
        $path = $goodsCategoryModel->where(['id' => $categoryId])->value('path');

        if (!empty($path)) {
            $parents = explode('-', $path);
            if (!$withCurrent) {
                array_pop($parents);
            }

            $param = cmf_param_lable($tag);
            $limit = empty($param['limit']) ? '' : $param['limit'];
            $field = empty($param['field']) ? 'id,parent_id,name' : $param['field'];

            if (!empty($parents)) {
                $data = $goodsCategoryModel
                     -> field($field)
                     -> where(['id' => ['in', $parents]])
                     -> where($where)
                     -> order('path ASC')
                     -> limit($limit)
                     -> select();
            }
        }
        return $data;
    }

    /**
     * 查询文章列表,不做分页
     * 注:此方法查询时关联三个表term_relationships,goodss,users;在指定查询字段(field),排序(order),指定查询条件(where)最好指定一下表名
     * @param string $tag <pre>查询标签,以字符串方式传入
     * 例："cid:1,2;field:goodss.goods_title,goodss.goods_content;limit:0,8;order:goods_date desc,listorder desc;where:id>0;"
     * ids:文章id,可以指定一个或多个文章id,以英文逗号分隔,如1或1,2,3
     * cid:文章所在分类,可指定一个或多个分类id,以英文逗号分隔,如1或1,2,3 默认值为全部
     * field:调用指定的字段
     *   如只调用goodss表里的id和goods_title字段可以是field:goodss.id,goodss.goods_title; 默认全部,
     *   此方法查询时关联三个表term_relationships,goodss,users;
     *   所以最好指定一下表名,以防字段冲突
     * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
     * order:排序方式,如按goodss表里的goods_date字段倒序排列：goodss.goods_date desc
     * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突</pre>
     * @param array $where 查询条件(只支持数组),格式和thinkphp的where方法一样,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突;
     * 
     */
    public static function goodsNotPaged($tag,$where=array()){
        // echo $tag;die;
        $param          = cmf_param_lable($tag);
        $param['where'] = $where;
        $content        = self::goods($param);
        return $content['goods'];
    }

    
    /**
     * 功能：根据分类文章分类ID 获取该分类下所有文章(包含子分类中文章)
     * 注:此方法查询时关联三个表term_relationships,goodss,users;在指定查询字段(field),排序(order),指定查询条件(where)最好指定一下表名
     * @author labulaka 2014-11-09 14:30:49
     * @param int $term_id 文章分类ID.
     * @param string $tag <pre>查询标签,以字符串方式传入
     * 例："cid:1,2;field:goodss.goods_title,goodss.goods_content;limit:0,8;order:goods_date desc,listorder desc;where:id>0;"
     * ids:文章id,可以指定一个或多个文章id,以英文逗号分隔,如1或1,2,3
     * cid:文章所在分类,可指定一个或多个分类id,以英文逗号分隔,如1或1,2,3 默认值为全部
     * field:调用指定的字段
     *   如只调用goodss表里的id和goods_title字段可以是field:goodss.id,goodss.goods_title; 默认全部,
     *   此方法查询时关联三个表term_relationships,goodss,users;
     *   所以最好指定一下表名,以防字段冲突
     * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
     * order:排序方式,如按goodss表里的goods_date字段倒序排列：goodss.goods_date desc
     * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突</pre>
     * @param array $where 查询条件(只支持数组),格式和thinkphp的where方法一样,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突;     
     */
    public static function goodsByTermId($id,$tag,$where=array()){
        $id             = intval($id);
        $param          = cmf_param_lable($tag);
        $param['where'] = $where;

        if(!is_array($where)){
            $where=array();
        }
        
        $ids = array();
        $ids = Db::name('goods_category')
            -> where("is_show=1 and ( id=$id OR path like '%-$id-%' )")
            -> order('id asc')
            -> column('id');

        if( !empty($ids) ){
            $param['where']['category_relate.category_id']=array('IN',$ids);
        }
        
        // pre($param,1);
        $content        = self::goods($param);
        return $content['goods'];
    }

    /**
     * 功能:查询文章列表,支持分页;<br>
     * 注:此方法查询时关联三个表term_relationships,goodss,users;在指定查询字段(field),排序(order),指定查询条件(where)最好指定一下表名
     * @param string $tag <pre>查询标签,以字符串方式传入
     * 例："cid:1,2;field:goodss.goods_title,goodss.goods_content;limit:0,8;order:goods_date desc,listorder desc;where:id>0;"
     * ids:文章id,可以指定一个或多个文章id,以英文逗号分隔,如1或1,2,3
     * cid:文章所在分类,可指定一个或多个分类id,以英文逗号分隔,如1或1,2,3 默认值为全部
     * field:调用指定的字段
     *   如只调用goodss表里的id和goods_title字段可以是field:goodss.id,goodss.goods_title; 默认全部,
     *   此方法查询时关联三个表term_relationships,goodss,users;
     *   所以最好指定一下表名,以防字段冲突
     * limit:数据条数,默认值为10,可以指定从第几条开始,如3,8(表示共调用8条,从第3条开始)
     * order:排序方式,如按goodss表里的goods_date字段倒序排列：goodss.goods_date desc
     * where:查询条件,字符串形式,和sql语句一样,请在事先做好安全过滤,最好使用第二个参数$where的数组形式进行过滤,此方法查询时关联多个表,所以最好指定一下表名,以防字段冲突</pre>
     * @param int $pagesize 每页条数,为0,false表示不分页
     * @param string $pagetpl 以字符串方式传入,例："{first}{prev}{liststart}{list}{listend}{next}{last}"
     * @return array 包括分页的文章列表<pre>
     * 格式:
     * array(
     *     "goodss"=>array(),//文章列表,array
     *     "page"=>""//生成的分页html,不分页则没有此项
     *     "count"=>100 //符合条件的文章总数,不分页则没有此项
     * )</pre>
     */
    public static function goodssPaged($tag,$pagesize=20,$pagetpl=''){
        return self::goodss($tag,array(),$pagesize,$pagetpl);
    }
}
